//
//  Statistics.hxx
//  sad
//
//  Created by Christopher Kemsley on 3/21/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#ifndef sad_Statistics_hxx
#define sad_Statistics_hxx


template <typename Type>
Value<Type> :: Value	( std::string const & name , Type const & initialValue )
:	mName ( name )
,	mValue ( initialValue )
,	mTime ( SCCurrentTime() )
,	mRecord ()
	{
	
	}
template <typename Type>
Value<Type> :: ~Value	()
	{
	/* Record the last state */
	SCInterval	time		=	SCCurrentTime() ;
	SCInterval&	duration	=	mRecord[mValue] ;
	duration	+=	( time - mTime ) ;
	
	/* Print out the results */
	LogStream stream = Log::statistics(mName) ;
	switch ( stream.preferredFormat() )
		{
			case LogStream::kPreferredFormatNatural : {
				stream << "	Last State = " << mValue << "\n" ;
				typename std::map<Type,SCInterval>::iterator	here	=	mRecord.begin() ;
				typename std::map<Type,SCInterval>::iterator	end		=	mRecord.end() ;
				while ( here != end )
					{
					SCInterval const & interval = here->second ;
					stream << "	" << (here->first) << "	" << interval.to_seconds() << "s	(" << interval << ")\n" ;
					here ++ ;
					}
			} break ;
			
			case LogStream::kPreferredFormatTSV : {
				stream << "Last State	" << mValue << "\n" ;
				typename std::map<Type,SCInterval>::iterator	here	=	mRecord.begin() ;
				typename std::map<Type,SCInterval>::iterator	end		=	mRecord.end() ;
				while ( here != end )
					{
					SCInterval const & interval = here->second ;
					stream << (here->first) << "	" << interval.to_seconds() << "s	" << interval << "\n" ;
					here ++ ;
					}
			} break ;
		}
	
	}




template <typename Type>
void	Value<Type> :: operator=	( Type const & value )
	{
	setValue ( value ) ;
	}
template <typename Type>
bool	Value<Type> :: operator!=	( Type const & value ) const
	{
	return mValue != value ;
	}
template <typename Type>
bool	Value<Type> :: operator==	( Type const & value ) const
	{
	return mValue == value ;
	}


template <typename Type>
Type const&	Value<Type> :: value () const
	{
	return mValue ;
	}
template <typename Type>
void		Value<Type> :: setValue ( Type const & value , bool retroactive )
	{
	if ( mValue == value ) return ;
	
	if ( retroactive )
		Log::states("Stats::Value") << mName << " = " << value << " (retroactive)" ;
	else
		Log::states("Stats::Value") << mName << " = " << value ;
	
	Type	stateToRecord	=	(retroactive?value:mValue) ;
	
	SCInterval	time		=	SCCurrentTime() ;
	
	// Warning: might not default to zero? (if you change this, change
	// the destructor too
	SCInterval&	duration	=	mRecord[stateToRecord] ;
	
	duration	+=	( time - mTime ) ;
	
	mTime	=	time ;
	mValue	=	value ;
	}







template <typename Type>
Accumulator<Type> :: Accumulator ( std::string const & name , std::string const & unit )
:	mName ( name )
,	mValue ( 0 )
,	mUnits ( unit )
,	mStartTime ( SCCurrentTime() )
	{
	
	}

template <typename Type>
Accumulator<Type> :: ~Accumulator ()
	{
	LogStream stream = Log::statistics(mName) ;
	
	
	switch ( stream.preferredFormat() )
		{
			case LogStream::kPreferredFormatNatural : {
				stream << "	Total Accumulation: " << mValue << "\n" ;
				
				SCInterval duration = SCCurrentTime() - mStartTime ;
				double durationInSeconds = duration.to_seconds() ;
				stream << "	Duration: " << durationInSeconds << "s	(" << duration << ")\n" ;
				
				stream << "	" << (((double)mValue)/durationInSeconds) << " " << mUnits << " per second\n" ;
			} break ;
			
			case LogStream::kPreferredFormatTSV : {
				stream << "Total Accumulation	" << mValue << "\n" ;
				
				SCInterval duration = SCCurrentTime() - mStartTime ;
				double durationInSeconds = duration.to_seconds() ;
				stream << "Duration	" << durationInSeconds << "s	" << duration << "\n" ;
				
				stream << mUnits << " per second	" << (((double)mValue)/durationInSeconds) << "\n" ;
			} break ;
		}
	}

template <typename Type>
void	Accumulator<Type> :: operator +=	( Type const & value )
	{
	mValue += value ;
	}









#endif
